#pragma once

#include <time.h>
#include <unistd.h>
#include "data.hpp"

extern cloud::DataManager *data; // 声明外部变量

namespace cloud
{
    class HotManager
    {
    private:
        std::string _back_dir;    // 备份文件存储目录
        std::string _pack_dir;    // 压缩包存储目录
        std::string _pack_suffix; // 压缩包后缀
        int _hot_time;            // 热点判断时间

    private:
        // 判断文件是否为非热点文件
        bool HotJudge(const std::string &filename)
        {
            FileUtil fu(filename);
            time_t last_atime = fu.LastATime(); // 获取文件最后一次访问时间
            time_t cur_time = time(NULL);       // 获取当前系统时间
            // 差值超过热点判断时间，则为非热点文件
            if (cur_time - last_atime > _hot_time)
                return true;
            return false;
        }

    public:
        HotManager()
        {
            Config *config = Config::GetInstance();
            _back_dir = config->GetBackDir();
            _pack_dir = config->GetPackDir();
            _pack_suffix = config->GetPackFileSuffix();
            _hot_time = config->GetHotTime();

            // 如果两个目录不存在，则创建
            FileUtil back_dir(_back_dir);
            FileUtil pack_dir(_pack_dir);
            if (back_dir.Exists() == false)
                back_dir.CreateDirectory();
            if (pack_dir.Exists() == false)
                pack_dir.CreateDirectory();
        }

        // 热点管理
        void RunModule()
        {
            // 服务端热点管理要不停的检测所有备份的文件，所以是一个死循环
            while (true)
            {
                // 1.遍历备份文件目录，获取所有已备份文件信息
                FileUtil fu(_back_dir);
                std::vector<std::string> v;
                // 调用ScanDirectory接口获取所有的文件的相对路径信息放入vector
                fu.ScanDirectory(v);

                // 2.遍历所有文件判断其是否为非热点文件
                for (auto &file : v)
                {
                    if (HotJudge(file) == false) // 热点文件不处理
                        continue;

                    // 3.非热点文件则进行压缩处理
                    FileUtil tmp(file);
                    // 调Compress压缩的话要传的是你压缩后要放入到哪个压缩包
                    // 即该文件对应的压缩包存储路径

                    // 所有要先获取到文件的压缩包存储路径信息
                    BackupInfo info;

                    // 通过文件的实际存储路径获取对应文件的信息
                    // cloud::DataManager *data上面已声明
                    if (data->GetOneByRealPath(file, info) == false)
                    {
                        //==fasle则说明哈希表中没有该备份文件的信息（正常情况下是不会没有信息的）
                        info.InitBackupInfo(file); // 初始化该文件的所有信息
                        data->Insert(info);        // 插入该文件信息
                    }

                    tmp.Compress(info._pack_path); // 这里获取文件的压缩包存储路径传入

                    // 4.压缩后删除原文件，修改压缩标志位
                    tmp.Remove();
                    info._pack_flag = true;

                    // 更新信息
                    data->Update(info);
                }

                usleep(1000); // 休眠1000微秒（1毫秒），避免空目录的时候疯狂进行逻辑判断导致CPU使用率过高
            }
        }
    };
}